// Copyright (C) 2010 Razvan Constantin <razvan.constantin@rconst.net>
//
// This file is part of FileBow.
//
// FileBow is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// FileBow is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FileBow.  If not, see <http://www.gnu.org/licenses/>.

#ifndef FILEBOW_LOGIC_FILE_SCORER_H__
#define FILEBOW_LOGIC_FILE_SCORER_H__

#include <map>
#include <vector>

#include "common/common.h"
#include "logic/path-tree.h"

namespace filebow {

/**
 * Base class for file scorers.
 * The total score for a node is the sum of all scores provided by scorers
 * on the node itself on or on an ancestor node.
 */
class FileScorer {

  /**
   * Called when a directory requires to be scored.
   * Returned score is applied recursively to all sub directories.
   * @param dirNode Directory node.
   * @return The score for the directory.
   */
  public: virtual int ScoreDir(const PathTree::Node* dirNode) const;

  /**
   * Called when a file requires to be scored.
   * @param fileNode File directory.
   * @return The score for the file.
   */
  public: virtual int ScoreFile(const PathTree::Node* fileNode) const;

  DECLARE_DEFAULTS(FileScorer);
};

/**
 * Default scorer implementation which replies given scores.
 */
class DefaultScorer : public FileScorer {

  /**
   * Sets the score for a node.
   */
  public: virtual void SetScore(const PathTree::Node* node, int score);

  /** @inheritDoc */
  public: virtual int ScoreDir(const PathTree::Node* node) const;

  /** @inheritDoc */
  public: virtual int ScoreFile(const PathTree::Node* node) const;

  /** Scores map. */
  private: typedef std::map<const PathTree::Node*, int> NodeMap;
  private: NodeMap scores;
};

/**
 * Scorer which boost scores for files with similar names to the given name.
 */
class SimilarScorer : public FileScorer {

  /**
   * Constructor.
   */
  public: SimilarScorer(const std::string& basename);

  /** @inheritDoc */
  public: virtual int ScoreFile(const PathTree::Node* node) const;

  /** Similarity base name. */
  private: std::string basename;
};

/**
 * Scorer which boost scores for files close to the given base path.
 */
class ClosestScorer : public FileScorer {

  /**
   * Constructor.
   * @param baseDirNode Reference directory for closest comparison. Not owned.
   */
  public: ClosestScorer(const PathTree::Node* baseDirNode);

  /** @inheritDoc */
  public: virtual int ScoreDir(const PathTree::Node* node) const;

  /** Node for the base directory. Not owned. */
  private: const PathTree::Node* dirNode;
};

/**
 * Composite scorer which allows aggregation of multiple scorers as one.
 */
class CompositeScorer : public FileScorer {
  // Scorers. Takes ownership of the scorer.
  public: void Add(FileScorer* scorer) { mScorers.push_back(scorer); }

  // @Override.
  public: virtual int ScoreDir(const PathTree::Node* node) const;
  // @Override.
  public: virtual int ScoreFile(const PathTree::Node* node) const;

  // Scorers.
  private: std::vector<FileScorer*> mScorers;

  DECLARE_DEFAULTS(CompositeScorer);
};

} // namespace filebow

#endif // FILEBOW_LOGIC_FILE_SCORER_H__
